/**
   ActivatableChevalDBServerImpl Implemtation class:
   It extends Activatable clas and implments the ChevalDBServer
   interface; returns meta data and record based on a sql statements.
       The object of Activatable class will be started by remote client
   or restarted by activation service when a reference to an object is
   made from remote client and no object is active.
*/
// TemperatureServerImpl definition
import java.rmi.activation.*;
import java.rmi.MarshalledObjct;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.sql.*;

public class ActivatableChevalDBServerImpl extends Activatable implements ChevalDBServer {
   Vector			rows = null ;
   String			heading;
   private Connection		cnn;
   private Statement		stmt = null;
   private String		name = "";

   String url = "jdbc:oracle:thin:@cheval:1521:TEST";
   String usr = "scott" ;
   String pwd = "tiger" ;
   int    hitCount = 1;

   // 'Regular' constructor used to create a pre-activated server.
   public ActivatableChevalDBServerImpl(String name, String src, int port)
      throws RemoteException, ActivationException, IOException {
      super(src, new HarshalledObject(name), false, port);
      myName = name;
      System.out.println("Initialization constructor is called");
      connectToDatabase();
   }

   // Constructor called by activation runtime to reactivate and export server.
   protected ActivatableChevalDBServerImpl(ActivationID id, MarshalledObject arg )
	throws RemoteException {
      super(id, 0);
      System.out.println("Activating server");
      // Check incoming data passed in with activation request.
      try {
	Object obj = arg.get();
	if ( obj instanceof String ) myName = (String) obj;
	else System.out.println("Unknown argument on activation: " + arg);
      } catch (Exception e) { System.out.println("Error in received argument to activate server"); }
      connectToDatabase();
   }

   
   private void connectToDatabase() {

        System.err.println( "Connecting to database..." );

	try { DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
	} catch(SQLException e) {
			System.err.print("ClassNotFoundException: ");
			System.err.println(e.getMessage());}
	try {
		cnn = DriverManager.getConnection(url, usr, pwd) ;
		stmt = cnn.createStatement() ;
		System.err.println("Connected to database!");
	} catch( SQLException e ) { System.err.println(e.toString()) ; }
          catch( Exception e ) { e.printStackTrace(); }
   }

   public void finalize() { 
	try { stmt.close(); cnn.close(); }
	catch (SQLException e) { System.err.println(e.toString()); }
   }

   public Vector getResultSet(String sql)  throws RemoteException
   {	try {
		String SQL = null;
		if ( sql != null ) SQL = sql.toUpperCase();

		{ int k = sql.lastIndexOf(";");
		  if ( k > 0 ) sql = sql.substring(0, k);
		}

		if (SQL.lastIndexOf("DELETE")>=0 ) sql = null;
		if (SQL.lastIndexOf("UPDATE")>=0 ) sql = null;
		if (SQL.lastIndexOf("SELECT")< 0 ) sql = null;

		if ( sql == null ) sql = "SELECT * FROM EMP";

		if ( rows != null ) rows.clear();
		rows = new Vector(30, 10);
		ResultSet rs = stmt.executeQuery(sql) ;
		ResultSetMetaData mdata = rs.getMetaData();
		int colCnt = mdata.getColumnCount();
		DBRow lenRow = new DBRow(colCnt), row = new DBRow(colCnt);
		
		// get column heading and their display lengths.
		for ( int i = 1; i <= colCnt; i ++ ) {
			int len = mdata.getColumnDisplaySize(i);
			switch( mdata.getColumnType(i) ) {
		   		case Types.NUMERIC: len = 10; break;
		   		case Types.DECIMAL: len = 10; break;
		   		case Types.DATE:    len = 10; break;
		   		case Types.TIME:    len = 10; break;
		   		case Types.TIMESTAMP: len = 10; break;
			}
			lenRow.setCol(i-1, len + "");
			row.setCol(i-1, mdata.getColumnName(i));
		}
		rows.addElement(lenRow); rows.addElement(row);

		// Get rows and coumns.
		int k = 2;
		String s ;
		while ( rs.next() ) {
		    row = new DBRow(colCnt);
		    for (int i = 1; i <= colCnt; i ++) {
			s = rs.getString(i);
			if ( s == null ) row.setCol(i-1, "");
			else if ( s.length() > Integer.parseInt(lenRow.getCol(i-1)) )
		    		row.setCol(i-1, s.substring(0,
					Integer.parseInt(lenRow.getCol(i-1))));
			     else
		    		row.setCol(i-1, rs.getString(i) + "");
		    }
		    rows.addElement(row);
		    k++;
		}
		rs.close(); rows.trimToSize();
		System.out.println(Calendar.getInstance().getTime().toString() +
					" Request No: " + hitCount++);
		return rows;
	} catch ( SQLException e ) {
	     System.err.println ("Error in getResultSet(): " +e.toString());
	     System.err.println("SQL Statement: " + sql); }
	  return rows;
   }

   public static void main( String args[] ) throws Exception
   {     
      System.err.println(
         "Initializing DB server: please wait." );

      // create server object
      ChevalDBServerImpl temp = new ChevalDBServerImpl();

      // bind TemperatureServerImpl object to the rmiregistry
      String serverObjectName = "//localhost/ChevalDBServer";
      Naming.rebind( serverObjectName, temp );
      System.err.println( "The "+ serverObjectName + " is up and running." );
   }
}

